package org.apache.skywalking.apm.plugin.spring.annotations;

import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.DeclaredInstanceMethodsInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
import org.apache.skywalking.apm.agent.core.plugin.match.ClassAnnotationMatch;
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
import org.apache.skywalking.apm.agent.core.plugin.match.IndirectMatch;
import org.apache.skywalking.apm.agent.core.plugin.match.RegexMatch;
import org.apache.skywalking.apm.agent.core.plugin.match.logical.LogicalMatchOperation;
import org.apache.skywalking.apm.plugin.spring.annotations.SpringAnnotationConfig.Plugin.SpringAnnotation;
import org.apache.skywalking.apm.util.StringUtil;

public abstract class AbstractSpringBeanInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
    private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.spring.annotations.SpringAnnotationInterceptor";
    public static final String INTERCEPT_GET_SKYWALKING_DYNAMIC_FIELD_METHOD = "getSkyWalkingDynamicField";
    public static final String INTERCEPT_SET_SKYWALKING_DYNAMIC_FIELD_METHOD = "setSkyWalkingDynamicField";

    public AbstractSpringBeanInstrumentation() {
    }

    public final ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
        return new ConstructorInterceptPoint[0];
    }

    public final InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
        return new InstanceMethodsInterceptPoint[]{new DeclaredInstanceMethodsInterceptPoint() {
            public ElementMatcher<MethodDescription> getMethodsMatcher() {
                return ElementMatchers.isPublic().and(ElementMatchers.not(ElementMatchers.isDeclaredBy(Object.class)).and(ElementMatchers.not(ElementMatchers.named("getSkyWalkingDynamicField"))).and(ElementMatchers.not(ElementMatchers.named("setSkyWalkingDynamicField"))));
            }

            public String getMethodsInterceptor() {
                return "org.apache.skywalking.apm.plugin.spring.annotations.SpringAnnotationInterceptor";
            }

            public boolean isOverrideArgs() {
                return false;
            }
        }};
    }

    protected ClassMatch enhanceClass() {
        return (ClassMatch) (StringUtil.isEmpty(SpringAnnotation.CLASSNAME_MATCH_REGEX) ? ClassAnnotationMatch.byClassAnnotationMatch(new String[]{this.getEnhanceAnnotation()}) : LogicalMatchOperation.and(new IndirectMatch[]{RegexMatch.byRegexMatch(SpringAnnotation.CLASSNAME_MATCH_REGEX.split(",")), ClassAnnotationMatch.byClassAnnotationMatch(new String[]{this.getEnhanceAnnotation()})}));
    }

    protected abstract String getEnhanceAnnotation();
}